perm filename STRUCT.LS1[LSP,JRA]1 blob
sn#099701 filedate 1974-04-26 generic text, type C, neo UTF8
COMMENT ⊗ VALID 00010 PAGES
C REC PAGE DESCRIPTION
C00001 00001
C00002 00002 prog ::= struct[defn:decsbdy:form]
C00004 00003 vars ::= seq[var]
C00005 00004 The evaluator
C00008 00005 find[n:vare:environ]
C00009 00006 primitive[f:primitivea:forms]sexpr
C00010 00007 An example:
C00011 00008 evgen({x,y,z},
C00013 00009 Try environ....
C00014 00010 The first version of eval corresponds to the LISP A-LIST eval.
C00015 ENDMK
C⊗;
prog ::= struct[defn:decs;bdy:form]
form ::= var
::= const
::= conditional
::= f_app
::= closure
::= generic
var ::= id
const ::= primitive
::= lambda
::= farg
::= label
::= sexpr
sexpr ::= atom
::= dtpr
conditional ::= seq[clause]
clause ::= struct[test:form,consequent:form]
f_app ::= struct[op:form;args:forms]
lambda ::= struct[formals:vars;body:form]
label ::= bind
closure ::= form
environ ::= seq[bind]
bind ::= struct[name:var,value;form]
farg ::= struct[fun:form;st:environ]
dtpr ::= struct[car:sexpr;cdr:sepxr]
primitive ::= car
::= cdr
::= cons
::= eq
::= atom
generic ::= struct[dispat:vars;body:matchs]
match ::= struct[pats:pats;repl:form]
pat ::= struct[m:mode;vars:vars]
dec ::= struct[n:var;m:mode]
mode ::=
vars ::= seq[var]
forms ::= seq[form]
matchs ::= seq[match]
modes ::= seq[mode]
pats ::= seq[pat]
decs ::= seq[dec]
The evaluator
eval[e:form;a:environ]form
generic(e)
[var] => find(e,a)
[const] => e
[conditional] => evcond(e;a)
[f_apply(u,v)] => apply(u,evlis(v,a),a)
[closure(f)] => farg(f,a)
[generic(d,mats)] => evgen(d,mats,a)
end;
apply[f;form;a:forms;st:environ] form
generic(f)
[const] => c_apply(f,a,st)
apply(eval(f,st)a,st)
end
c_apply[f:const;a;forms;st:environ]form
generic(f)
[primitive] => p-apply(f,a)
[lambda(v,b)] => eval(b,environ(binds(v,s),st))
[label(n,def)] => apply(n,a,environ(binds(n,def)st))
[farg(f,e)] => apply(f,a,e)
end;
evcond[b:conditional;st:environ] form
on(b)
[ε] => FALSE;
[clause(test,val)] => {eval(test,st) => eval(val,st)}
end;
evgen[vs:vars;bdy:matchs;a:environ] form
on(bdy)
[ε] => LOSS;
[match(u,v)] => {chk_modes(u,vs) => eval(v;environ(bindr(u,vs),a))
end;
chk_modes[u:pats;vs:vars] boolean
on(pats,vars)
[ε] => TRUE;
[pat(m1,*),v] => {m1=mode(v) => TRUE}
end;
bindr[u:pats;vs:vars] environ
on(pats,vars)
[ε] => ε
[pat(*,vs),v] → bind*(vs,v)
end;
bind*[vs:vars;v:var] environ
PRIMITIVE BINDER
ex. vs = (a,b,c) and v is struct[x:xx;y:yy;z:zz ...]
then make environ of form ((a . xx),(b . yy) ..)
find[n:var;e:environ]
on(e)
[ε] => LOSS
[bind(u,v)] => {n=u => v}
end;
evlis[args:forms;st:environ] forms
on(args)
[ε] => ε;
[a] => eval(a,st)
end;
binds[vs:vars;as:args]environ
on(vs,as)
[ε] => ε;
[v,a] => bind(v,a)
end;
primitive[f:primitive;a:forms]sexpr
generic[f]
[car] => evcar[a]
...
end;
evcar[a:forms]sexpr
on(a)
[ε] => LOSS
[(b,c)] => LOSS
car(a)
end
car[x:dtpr]x.car
cdr[x:dtpr]x.cdr
cons[x:sexpr;y:sexpr] dtpr(x,y)
eq[x:atom;y:atom] boolean
{x=y => TRUE;FALSE}
atom[x;sexpr]boolean
generic(x)
[atom] => TRUE
FALSE
end;
An example:
let [ ...] be fences for structures and
{ ... } be fences for sequences.
Thus abstract syntax of
x ::= struct[a:b;c:d]
b ::= seq[1,2,3]
represents an instance of an x as:
[{1,2,3},d]
Thus
generic(x,x,z)
[t1(a,b)] => foo(a,b);
[*,t2(c,d)] => foo1(c,d);
end
could go to:
[{x,y,z},
{[{[t1, {a,b)}], ε, ε}, [foo, {a,b}],
[{ε, [t1, {c,d)}], ε}, [foo, {c,d}]
}
]
now for execution of evgen on hhs.
First the evaluation is intuitive rather than precise we will use values and
variables interchangeably in "calling sequrnce" no confusion should result.
evgen({x,y,z},
{[{[t1, {a,b)}], ε, ε}, [foo, {a,b}],
[{ε, [t1, {c,d)}], ε}, [foo, {c,d}]
},
st) st is name of some envirionment
Note that types match.
(match( {[t1, {a,b)}], ε, ε},
[foo, {a,b}]) ⊗ {[{ε, [t1, {c,d)}], ε}, [foo, {c,d}]
})
happens now with obvious bindings on u,v, and m.
chkmodes is called:
chkmodes( {[t1, {a,b)}], ε, ε},
{x,y,z} )
now get
(pat(t1,*) ⊗ {ε, ε}, x⊗{y, z}); look at mode of x: is it t1?
assuming it is return TRUE to evgen and perform:
eval( [foo, {a, b}]
environ( bindr ( {[t1, {a, b)}], ε, ε},
{x,y,z} ),
st)
)
Try environ....
try bindr ....
(pat(*, {a,b}) ⊗{ε,ε}) , (x⊗{y,z}) goes to
environ( bindr( {ε, ε}, {y,z}),
bind*( {a,b} ,x)
)
finally should end up at:
environ( ε, bind*( {a,b} ,x))
bind* is primitive and clever. It fetches the data strucure NAMED by x
and associated the appropriate element in that named structure with the
NAMES is the sequence in its frist arg. bind* is to return a data structure
of type "environ". But that's easy and FAST assuming the obvious rep.
for structures and sequences.
The first version of eval corresponds to the LISP A-LIST eval.
Perhaps a more realistic version would be a deep-binding eval.
And here is is:
This should also show what d.s. are necessary for incestuous implementation.
as usually there is the name-value stack:
stack_ent ::= struct[name:var;mode:mode;value:ptr_any]
first try storing mode of var with var, rather than with value
reasons: mode is of var not of value;since type checking should
handle match. store pure values; accessor returns mode and value.
find rummages down name stack for name match and return mode-value.